package com.shop.zzh.utils;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;

/**
 * @program: zzh
 * @description: ftp工具类
 * @author: zhuzh
 * @create: 2019-12-06 09:58
 **/
public class FtpUtils {

	private static Logger logger = LoggerFactory.getLogger(FtpUtils.class);

	/**
	 * 获取FTPClient对象
	 *
	 * @param ftpHost     FTP主机服务器
	 * @param ftppassWord FTP 登录密码
	 * @param ftpUserName FTP登录用户名
	 * @param ftpPort     FTP端口 默认为21
	 * @return
	 */
	public static FTPClient getFTPClient(String ftpHost, int ftpPort,
										 String ftpUserName, String ftppassWord)throws Exception{
		FTPClient ftpClient = new FTPClient();
		ftpClient.setControlEncoding("UTF-8");
		ftpClient.connect(ftpHost, ftpPort);// 连接FTP服务器
		ftpClient.login(ftpUserName, ftppassWord);// 登陆FTP服务器
		if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
			System.out.println("未连接到FTP，用户名或密码错误。");
			ftpClient.disconnect();
		}else {
			System.out.println("FTP连接成功。");
		}
		return ftpClient;
	}


	/**
	 * 断开与远程服务器的连接
	 */
	public static void disconnectFTPClient(FTPClient ftpClient) {
		try {
			ftpClient.logout(); // 退出登录
			ftpClient.disconnect();  // 关闭连接
		} catch (IOException e) {
			throw new RuntimeException("关闭ftp连接失败.", e);
		}
	}

	/**
	 * 上传文件（可供Action/Controller层使用）
	 * @param basePath FTP服务器基础目录
	 * @param filePath FTP服务器保存目录
	 * @param fileName 上传到FTP服务器后的文件名称
	 * @param inputStream 输入文件流
	 * @return
	 */
	public static boolean uploadFile(FTPClient ftpClient, String basePath, String filePath,
									 String fileName, InputStream inputStream)throws Exception{
		boolean result = false;
		//切换到上传目录
		if (!ftpClient.changeWorkingDirectory(basePath + filePath)) {
			//如果目录不存在创建目录
			filePath = filePath.replace("\\", "/");
			String[] dirs = filePath.split("/");
			String tempPath = "";
			for (String dir : dirs) {
				if (StringUtils.isBlank(dir)) {
					continue;
				}
				tempPath += "/" + dir;
				if (!ftpClient.changeWorkingDirectory(tempPath)) {
					if (!ftpClient.makeDirectory(tempPath)) {
						throw new RuntimeException("无法创建目录");
					}
					ftpClient.changeWorkingDirectory(tempPath);
				}
			}
		}

		// 中文支持
		ftpClient.setControlEncoding("UTF-8");
		// 因为ftp server可能每次开启不同的端口来传输数据，但是在linux上或者其他服务器上面，由于安全限制，可能某些端口没有开启，所以就出现阻塞
		ftpClient.enterLocalPassiveMode();
		//设置上传文件的类型为二进制类型
		ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
		ftpClient.setBufferSize(1024*1024);
		BufferedInputStream input = new BufferedInputStream(inputStream);
		//上传文件
		if (!ftpClient.storeFile(fileName, input)) {
			return result;
		}
		inputStream.close();
		input.close();
		result = true;
		return result;
	}


	/**
	 * 上传文件（可对文件进行重命名）
	 * @param basePath FTP服务器基础目录
	 * @param filePath FTP服务器保存目录
	 * @param fileName 上传到FTP服务器后的文件名称
	 * @param originfileName 待上传文件的名称（绝对地址）
	 * @return
	 */
	public static boolean uploadFileChangeName(FTPClient ftpClient, String basePath, String filePath,
											   String fileName, String originfileName)throws Exception{
		boolean result = false;
		InputStream inputStream = new FileInputStream(new File(originfileName));
		result = uploadFile(ftpClient, basePath, filePath, fileName, inputStream);
		return result;
	}

	/**
	 * 上传文件（不可以进行文件的重命名操作）
	 * @param basePath FTP服务器基础目录
	 * @param filePath FTP服务器保存目录
	 * @param originfileName 待上传文件的名称（绝对地址）
	 * @return
	 */
	public static boolean uploadFileNotChangeName(FTPClient ftpClient,
												  String basePath, String filePath,
												  String originfileName)throws Exception{
		boolean result = false;
		String fileName = new File(originfileName).getName();
		InputStream inputStream = new FileInputStream(new File(originfileName));
		result = uploadFile(ftpClient, basePath, filePath, fileName, inputStream);
		return result;
	}


	/**
	 * 删除文件
	 * @param filePath FTP服务器保存目录
	 * @param fileName 要删除的文件名称
	 * @return
	 */
	public static boolean deleteFile(FTPClient ftpClient, String filePath, String fileName)throws Exception{

		boolean result = false;
		ftpClient.setControlEncoding("UTF-8"); // 中文支持
		ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
		ftpClient.enterLocalPassiveMode();
		ftpClient.changeWorkingDirectory(filePath);  //切换FTP目录
		ftpClient.dele(fileName);
		result = true;
		return result;
	}

	/**
	 * 单文件下载
	 * @param filePath FTP服务器保存目录
	 * @param fileName 文件名称
	 * @param localpath 下载后的文件路径
	 * @return
	 */
	public static boolean downloadFileForLocal(FTPClient ftpClient,
											   String filePath, String fileName,
											   String localpath)throws Exception{
		boolean result = false;
		//切换FTP目录
		ftpClient.setControlEncoding("UTF-8"); // 中文支持
		ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
		ftpClient.enterLocalPassiveMode();
		ftpClient.changeWorkingDirectory(filePath);
		FTPFile[] ftpFiles = ftpClient.listFiles();
		if(ftpFiles!=null&&ftpFiles.length>0){
			for(FTPFile file : ftpFiles){
				if(fileName.equalsIgnoreCase(file.getName())){
					File localFile = new File(localpath + "/" + file.getName());
					OutputStream os = new FileOutputStream(localFile);
					result = ftpClient.retrieveFile(file.getName(), os);
					os.close();
					break;
				}
			}
		}
		return result;
	}

	/**
	 * ftp浏览器单文件下载
	 * @param ftpClient
	 * @param filePath
	 * @param fileName
	 * @param response
	 * @throws Exception
	 */
	public boolean downloadFileForBrowser(FTPClient ftpClient,String filePath,
										  String fileName, HttpServletResponse response) throws Exception {

		boolean result = false;
		// 开启输出流弹出文件保存路径选择窗口
		response.setContentType("application/octet-stream;charset=UTF-8");
		response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
		OutputStream out = response.getOutputStream();
		ftpClient.setControlEncoding("UTF-8"); // 中文支持
		ftpClient.enterLocalPassiveMode();
		ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
		ftpClient.changeWorkingDirectory(filePath);
		FTPFile[] ftpFiles = ftpClient.listFiles();
		if(ftpFiles!=null&&ftpFiles.length>0) {
			for (FTPFile file : ftpFiles) {
				if (fileName.equalsIgnoreCase(file.getName())) {
					result = ftpClient.retrieveFile(fileName, out);
					out.close();
					break;
				}
			}
		}
		return result;
	}

	/**
	 * 读取ftp服务器文内容
	 * @param filePath FTP服务器保存目录
	 * @param fileName 文件名称
	 * @return  byte[]  返回文件字节数组
	 */
	public static byte[] getFtpFileContent(FTPClient ftpClient, String filePath, String fileName)throws Exception{

		byte[] content = null;
		//切换FTP目录
		ftpClient.setControlEncoding("UTF-8"); // 中文支持
		ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
		ftpClient.enterLocalPassiveMode();
		ftpClient.changeWorkingDirectory(filePath);
		FTPFile[] ftpFiles = ftpClient.listFiles();
		if(ftpFiles!=null&&ftpFiles.length>0){
			for(FTPFile file : ftpFiles){
				if(fileName.equalsIgnoreCase(file.getName())){
					InputStream in = ftpClient.retrieveFileStream(file.getName());
					if(in!=null){
						ByteArrayOutputStream output = new ByteArrayOutputStream();
						IOUtils.copy(in, output);
						content = output.toByteArray();
						in.close();
						output.close();
						ftpClient.completePendingCommand();
					}
					break;
				}
			}
		}
		return content;
	}

	/**
	 * 重命名ftp文件名称
	 * @param ftpClient ftp客户端
	 * @param filePath 文件工作目录
	 * @param fileOriName 文件原名
	 * @param fileNewName 文件新名称
	 * @return
	 * @throws Exception
	 */
	public static boolean renameFtpFile(FTPClient ftpClient, String filePath,
										String fileOriName, String fileNewName) throws Exception{

		boolean result = false;
		ftpClient.setControlEncoding("UTF-8"); // 中文支持
		ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
		ftpClient.enterLocalPassiveMode();
		ftpClient.changeWorkingDirectory(filePath);
		FTPFile[] ftpFiles = ftpClient.listFiles();
		if(ftpFiles!=null&&ftpFiles.length>0) {
			for (FTPFile file : ftpFiles) {
				if (fileOriName.equalsIgnoreCase(file.getName())) {
					result = ftpClient.rename(fileOriName, fileNewName);
				}
			}
		}
		return result;
	}


	// 测试
	public static void main(String[] args) throws Exception{

		int port = 21;
		String hostName = "172.16.61.161";
		String userName = "ftp";
		String passWord = "123456";
		String basePath = "";
		String filePath = "/erp_upload_files/AEA_ITEM_MAT/b2c557c9-7e86-43ba-9540-a20c949a0ea2";
		String fileName = "1545877676553.png";
		String originfileName = "D:/erp_upload_files/AEA_ITEM_MAT/b2c557c9-7e86-43ba-9540-a20c949a0ea2/1545877676553.png";
		// 连接ftp
		FTPClient ftpClient = getFTPClient(hostName, port, userName, passWord);
		// 上传文件
//        uploadFileChangeName(ftpClient,basePath, filePath, fileName, originfileName);
		// 重命名文件
		renameFtpFile(ftpClient, "/erp_upload_files/AEA_ITEM_MAT/b2c557c9-7e86-43ba-9540-a20c949a0ea2",
				"1545877676553.png", "jjt.png");
		// 关闭ftp连接
		disconnectFTPClient(ftpClient);
	}

}
